/* $RCSFile: ADNDynSalesOrder.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/CRMWrapper3/DynEntities/ADNDynSalesOrder.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:33  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.Diagnostics;
using System.Collections;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using CrmSdk;

namespace AddonNice.CRMWrapper
{
	public class ADNDynSalesOrder : ADNDynSalesBase
	{
        public enum InternalSalesOrderState
        {
            Active      = 0, // Specifies that the sales order (order) is active.->Status New=1, Pending = 2
            Submitted   = 1, // Specifies that the sales order (order) is submitted.->Status  In Progress 3 
            Canceled    = 2, // Specifies that the sales order (order) is canceled.->Status No Money=4 
            Fulfilled   = 3, // Specifies that the sales order (order) is fulfilled.->Status  Complete = 100001 ,Partial = 100002
            Invoiced    = 4, // Specifies that the sales order (order) is invoiced. ->Status  Invoiced = 100003 
        }

        protected class Ftor: DFactor
        {
            public Ftor() : base(CrmStr.salesorder)
            {}

            public override Type DynType
            { get { return typeof(ADNDynSalesOrder); } }

            public override string DynTypename
            {   get{ return CrmStr.salesorder;}}

            public override DynEntity Build()
            {   return new ADNDynSalesOrder();}

            public override DynEntity Build(CRMWrapperBase w, InternalDynamicEntity dEntity, PropertyDescriptorCollection wproperties)
            {   return new ADNDynSalesOrder(w, dEntity, wproperties, null);}

            public override DynEntity Build(CRMWrapperBase w, string PrimaryFieldValue)
            {   return new ADNDynSalesOrder(w,PrimaryFieldValue);}

            public override DynEntity Build(CRMWrapperBase w,Guid PrimaryKeyValue)
            {   return new ADNDynSalesOrder(w,PrimaryKeyValue);}
        }

        static ADNDynSalesOrder(){new Ftor();} 

        /// <summary>
		/// Reserved for template methods: do not use directly
		/// </summary>
        public ADNDynSalesOrder(): base()
		{}

        public ADNDynSalesOrder(CRMWrapperBase w, string PrimaryFiedlValue)
			: base(w,CrmStr.salesorder)
		{
			name = PrimaryFiedlValue;
		}

		public ADNDynSalesOrder(CRMWrapperBase w, Guid CrmId)
			: base(w,CrmStr.salesorder, CrmId)
		{}

		public ADNDynSalesOrder(CRMWrapperBase w, InternalDynamicEntity e)
			: base(w,CrmStr.salesorder,e,null,null)
		{}

		public ADNDynSalesOrder(CRMWrapperBase w, InternalDynamicEntity e,PropertyDescriptorCollection prop,InternalColumnSet s)
			: base(w,CrmStr.salesorder,e,prop,s)
		{}

        public ADNDynSalesOrder(ResetWrapperHandler fn, string PrimaryFiedlValue)
			: base(fn,CrmStr.salesorder)
		{
			name = PrimaryFiedlValue;
		}

		public ADNDynSalesOrder(ResetWrapperHandler fn, Guid CrmId)
			: base(fn,CrmStr.salesorder, CrmId)
		{}

		public ADNDynSalesOrder(ResetWrapperHandler fn, InternalDynamicEntity e)
			: base(fn,CrmStr.salesorder,e,null,null)
		{}

		public ADNDynSalesOrder(ResetWrapperHandler fn, InternalDynamicEntity e,PropertyDescriptorCollection prop,InternalColumnSet s)
			: base(fn,CrmStr.salesorder,e,prop,s)
		{}
		
        /// <summary>
		/// Crm Key
		/// </summary>
        [CrmDynAttribute(CrmStr.salesorder)]
        public Guid salesorderid
		{
			get
			{
				return KeyPropertyValue(CrmStr.salesorderid);
			}
			set
			{
				AddKeyProperty(CrmStr.salesorderid, value);
			}
		}

        protected override void SetCrmIdProperty(Guid crmId)
        {
           if ( !dicProperty.ContainsKey(CrmStr.salesorderid) || KeyPropertyValue(CrmStr.salesorderid) != crmId )
                salesorderid    =   crmId;
        }

        public override Guid PrimaryKeyGuidValue
        {
           get
           {
                return salesorderid;
           }
           set
           {
               salesorderid    =   value;
           }
        }

        /// <summary>
        /// Gets or sets the priority of the order.
        /// High 2 Specifies high priority. 
        /// Low 0 Specifies low priority. 
        /// Medium 1 Specifies medium priority. 
        /// </summary>
        [CrmDynAttribute(CrmStr.salesorder)]
        public int prioritycode 
        {
            get
            {
                return PicklistPropertyIntValue(CrmStr.prioritycode);
            }
            set
            {
                AddPicklistProperty(CrmStr.prioritycode,value);
            }
        }

        /// <summary>
        /// Gets the priority name of the order.
        /// High 2 Specifies high priority. 
        /// Low 0 Specifies low priority. 
        /// Medium 1 Specifies medium priority. 
        /// </summary>
        public string prioritycodeLabel
        {
            get
            {
                if ( ContainsKey(CrmStr.prioritycode) )
                    return PicklistPropertyLabelValue(CrmStr.prioritycode);
                return string.Empty;
            }
        }
        
        /// <summary>
        /// Gets or sets the requested delivery date for the order.
        /// </summary>
        [CrmDynAttribute(CrmStr.salesorder)]
        public string requestdeliveryby
        {
            get
            {
                if ( ContainsKey(CrmStr.requestdeliveryby) )
                    return DateTimePropertyValue(CrmStr.requestdeliveryby);
                return string.Empty;
            }
            set
            {
                AddDateTimeProperty(CrmStr.requestdeliveryby,value);
            }
        }
 
        /// <summary>
        /// Gets or sets the requested delivery date for the order.
        /// </summary>
        public DateTime requestdeliverybyLocalDate
        {
            get
            {
                if ( ContainsKey(CrmStr.requestdeliveryby) )
                    return DateTimePropertyDate(CrmStr.requestdeliveryby,true);
                return CRMUtil.minDateTime;
            }
        }

        /// <summary>
        /// Gets or sets the date on which the order was fulfilled.
        /// </summary>
        [CrmDynAttribute(CrmStr.salesorder)]
        public string datefulfilled
        {
            get
            {
                if ( ContainsKey(CrmStr.datefulfilled) )
                    return DateTimePropertyValue(CrmStr.datefulfilled);
                return string.Empty;
            }
            set
            {
                AddDateTimeProperty(CrmStr.datefulfilled,value);
            }
        }
 
        /// <summary>
        /// Gets or sets the date on which the order was fulfilled.
        /// </summary>
        public DateTime datefulfilledLocalDate
        {
            get
            {
                if ( ContainsKey(CrmStr.datefulfilled) )
                    return DateTimePropertyDate(CrmStr.datefulfilled,true);
                return CRMUtil.minDateTime;
            }
        }
 
        /// <summary>
        /// Gets or sets the date on which the order was submitted. 
        /// </summary>
        [CrmDynAttribute(CrmStr.salesorder)]
        public string submitdate
        {
            get
            {
                if ( ContainsKey(CrmStr.submitdate) )
                    return DateTimePropertyValue(CrmStr.submitdate);
                return string.Empty;
            }
            set
            {
                AddDateTimeProperty(CrmStr.submitdate,value);
            }
        }

        /// <summary>
        /// Gets whether the order pricing is locked. 
        /// </summary>
        [CrmDynAttribute(CrmStr.salesorder)]
        public bool ispricelocked
        {
            get 
            {
                return BooleanPropertyValue(CrmStr.ispricelocked);
            }
            set
            {
            
                AddBooleanProperty(CrmStr.ispricelocked,value);
            }
        }

        /// <summary>
        /// Gets or sets the order number.  
        /// </summary>
        [CrmDynAttribute(CrmStr.salesorder)]
        public string ordernumber
        {
            get
            {
                return StringPropertyValue(CrmStr.ordernumber);
            }
            set
            {
                AddStringProperty(CrmStr.ordernumber,value);
            }
        }

        [CrmDynAttribute(CrmStr.salesorder)]
        public int submitstatus
        {
            get
            {
                return NumberPropertyValue(CrmStr.submitstatus);
            }
            set
            {
                AddNumberProperty(CrmStr.submitstatus,value);
            }
        }

        
        [CrmDynAttribute(CrmStr.salesorder)]
        public string submitstatusdescription
        {
            get
            {
                return StringPropertyValue(CrmStr.submitstatusdescription);
            }
            set
            {
                AddStringProperty(CrmStr.submitstatusdescription,value);
            }
        }

        /// <summary>
        /// virtual because on 'detail' records it is only a uniqueidentifier property
        /// </summary>
        [CrmDynAttribute(CrmStr.salesorder)]
        public Guid owningbusinessunit
        {
            get
            {
                return LookupPropertyValue(CrmStr.owningbusinessunit);
            }
            set
            {
                AddLookupProperty(CrmStr.owningbusinessunit,CrmStr.businessunit,value);
            }
        }
        
        /// <summary>
        /// Owner for this object
        /// </summary>
        [CrmDynAttribute(CrmStr.salesorder)]
        public override Guid ownerid
        {
            get
            {
                if ( ContainsKey(CrmStr.ownerid) )
                    return OwnerPropertyValue(CrmStr.ownerid);
                return Guid.Empty;
            }
            set
            {
                AddOwnerProperty(CrmStr.ownerid,CrmStr.systemuser,value);
            }
        }

        /// <summary>
        /// Sending -1 as eStatus will lead crm to take the default good value
        /// </summary>
        public void FulFill(int eStatus,string comment)
        {
            wrapper.Util.FulfillOrder(this,eStatus,comment);
        }

        /// <summary>
        /// Sending -1 as eStatus will lead crm to take the default good value
        /// </summary>
        public void Cancel(int eStatus,string comment)
        {
            wrapper.Util.CancelOrder(this,eStatus,comment);
        }

        // only one statuscode for state submited
        public void Submit()
        {
            wrapper.Util.SetStateOperation(CrmStr.salesorder,salesorderid,(int)InternalSalesOrderState.Submitted,-1);
        }

        // only one statuscode for state submited
        public void ActivePending()
        {
            wrapper.Util.SetStateOperation(CrmStr.salesorder,salesorderid,(int)InternalSalesOrderState.Active,2);
        }

        /// <summary>
        /// Sending null as cols will lead crm to take AllColumn
        /// </summary>
        public ADNDynInvoice ConvertToInvoice(InternalColumnSet cols)
        {
            return wrapper.Util.ConvertOrderToInvoice(this,cols);
        }
        /// <summary>
        /// Use a CreateCompound to create order and its orderdetails in Crm
        /// </summary>
        public virtual Guid Save(List<DynEntity> childs)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynSalesOrder Save BEG Order name: {0}", name),CRMDynTraceSwitch.Sw.Info);

            Guid OrderId                        =    Guid.Empty;
            try
            {
                //create compound request
                OrderId                         =   wrapper.adminCreateCompound(this,childs);
                EntityID                        =   OrderId;
                // read back to get all columns and ordernumber
                adminRetrieve();
            }
            catch (Exception exp)
            {
                if ( CRMDynTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ADNDynSalesOrder Save ex: {0}",exp),CRMDynTraceSwitch.Sw.Info);
                throw;
            }
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynSalesOrder Save END Id: {0}",OrderId),CRMDynTraceSwitch.Sw.Info);
            return OrderId;
        }

        public virtual bool SendMail(ResetWrapperHandler fn,string subject,string body,bool send)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
	            Trace.WriteLine("[V]ADNDynSalesOrder SendMail BEG.",CRMDynTraceSwitch.Sw.Info);
            try
            {
                /// we get the Membership user from customer
                ADNDynCustomer customer     =   null;
                string customerTp           =   customerType;
                switch (customerTp)
                {
                    case CrmStr.account:
                        customer            =   DynEntity.GetFromCache<ADNDynAccount>(CrmStr.account,wrapper,fn,customerid,true);
                        break;
                    case CrmStr.contact:
                        customer            =   DynEntity.GetFromCache<ADNDynContact>(CrmStr.contact,wrapper,fn,customerid,true);
                        break;
                    default:
                        return false;
                }

                ADNDynEmail cmail           =   new ADNDynEmail(fn,subject);
                cmail.SetOwnerFromUserId();
                cmail.description           =   body;
                cmail.AddDest(customer,customer.emailaddress1);
                ADNDynSystemUser DynSender  =   DynEntity.GetFromCache<ADNDynSystemUser>(CrmStr.systemuser,wrapper,fn,wrapper.userId,true);
                cmail.AddSender(DynSender, DynSender.internalemailaddress);
                cmail.directioncode         =   true;
                cmail.mimetype              =   "text/html";
                cmail.sender                =   DynSender.internalemailaddress;
                cmail.DefaultRegardingObjectName = CrmStr.salesorder;
                cmail.regardingobjectid     =   salesorderid;
                cmail.prioritycode          =   2; // high
                if ( CRMDynTraceSwitch.Sw.TraceVerbose )
		            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynSalesOrder SendMail to customer: '{0}', sender: '{1}'.",customer.emailaddress1,DynSender.internalemailaddress),CRMDynTraceSwitch.Sw.Info);
                cmail.adminCreate();
                if ( send) 
                    cmail.Send(true);
            }
            catch(Exception ex)
            {
                if ( CRMDynTraceSwitch.Sw.TraceError)
		            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ADNDynSalesOrder SendMail ex: '{0}'.",ex),CRMDynTraceSwitch.Sw.Info);
                return false;
            }
            return true;
        }


        /// <summary>
        /// Use tranmsitted template to send a mail
        /// If template body contains &lt;BODY&gt; replace it with the sent body, else add the body to instantiated template content
        /// </summary>
        public bool SendMailWithTemplate(ResetWrapperHandler fn,ADNDynTemplate dynTemp,ADNDynSystemUser mailOwner,string body,bool send)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
	            Trace.WriteLine("[V]ADNDynSalesOrder SendMailWithTemplate BEG.",CRMDynTraceSwitch.Sw.Info);
            try
            {
                /// we get the Membership user from customer
                ADNDynCustomer customer             =   null;
                string customerTp                   =   customerType;
                switch (customerTp)
                {
                    case CrmStr.account:
                        customer                    =   DynEntity.GetFromCache<ADNDynAccount>(CrmStr.account,wrapper,fn,customerid,true);
                        break;
                    case CrmStr.contact:
                        customer                    =   DynEntity.GetFromCache<ADNDynContact>(CrmStr.contact,wrapper,fn,customerid,true);
                        break;
                    default:
                        return false;
                }

                ADNDynEmail mail                    =   wrapper.Util.InstantiateTemplate(dynTemp,customer,true);
                mail.prioritycode                   =   prioritycode;
                if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                {
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynSalesOrder SendMailWithTemplate.description: [{0}].",mail.description),CRMDynTraceSwitch.Sw.Info);
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNDynSalesOrder SendMailWithTemplate.subject: [{0}].",mail.subject),CRMDynTraceSwitch.Sw.Info);
                }
                // complete actual mail with sender, dest and regarding
                mail.AddDest(customer);
                mail.AddSender(mailOwner);
                mail.DefaultRegardingObjectName     =   CrmStr.salesorder;
                mail.regardingobjectid              =   salesorderid;
                mail.ownerid                        =   mailOwner.systemuserid;
                if ( mail.description.Contains("<BODY>" ) )
                    mail.description                =   mail.description.Replace("<BODY>",body);
                else mail.description               =   mail.description + body;
                mail.adminCreate();
                if ( send) 
                    mail.Send(true);
            }
            catch(Exception ex)
            {
                if ( CRMDynTraceSwitch.Sw.TraceError)
		            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ADNDynSalesOrder SendMailWithTemplate ex: '{0}'.",ex),CRMDynTraceSwitch.Sw.Info);
                return false;
            }
            return true;
        }
    }
}
